package com.yxsk.relay.job.admin.controller;

import com.alibaba.fastjson.TypeReference;
import com.yxsk.relay.job.admin.core.log.EndpointLogService;
import com.yxsk.relay.job.admin.core.schedule.quartz.QuartzDynamicScheduleService;
import com.yxsk.relay.job.admin.data.entity.JobExecuteLog;
import com.yxsk.relay.job.admin.data.service.JobExecuteLogService;
import com.yxsk.relay.job.admin.exception.job.RelayTaskIrrevocableException;
import com.yxsk.relay.job.component.common.constant.UriConstant;
import com.yxsk.relay.job.component.common.exception.remote.RemoteCallException;
import com.yxsk.relay.job.component.common.protocol.caller.RemoteCaller;
import com.yxsk.relay.job.component.common.protocol.message.base.ResultResponse;
import com.yxsk.relay.job.component.common.protocol.message.log.delete.LogDeleteRequestDto;
import com.yxsk.relay.job.component.common.protocol.message.log.delete.LogDeleteResponseDto;
import com.yxsk.relay.job.component.common.protocol.message.log.query.LogQueryRequestDto;
import com.yxsk.relay.job.component.common.protocol.message.log.query.LogQueryResponseDto;
import com.yxsk.relay.job.component.common.utils.DateUtils;
import com.yxsk.relay.job.component.common.utils.SerialNoUtils;
import com.yxsk.relay.job.component.common.vo.ExecuteResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author 11376
 * @CreaTime 2019/6/30 14:04
 * @Description
 */
@Slf4j
@Api("任务执行查询接口")
@RequestMapping("/log")
@RestController
public class JobExecuteLogController {

    @Autowired
    private RemoteCaller remoteCaller;
    @Autowired
    private JobExecuteLogService executeLogService;
    @Autowired
    private QuartzDynamicScheduleService dynamicScheduleService;
    @Autowired
    private EndpointLogService logService;

    @ApiOperation("查询执行日志")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "jobExecuteId", value = "任务执行Id", required = true),
            @ApiImplicitParam(name = "startLine", value = "起始行数"),
            @ApiImplicitParam(name = "endLine", value = "结束行数"),
    })
    @GetMapping("/query")
    public ResultResponse<LogQueryResponseDto> query(@RequestParam("jobExecuteId") String jobExecuteId,
                                                     @RequestParam(name = "startLine", required = false) Long startLine,
                                                     @RequestParam(name = "endLine", required = false) Long endLine) {
        JobExecuteLog executeLog = this.executeLogService.findById(jobExecuteId);
        if (executeLog == null) {
            return ResultResponse.fail("EXECUTE-LOG-9999", "执行记录未找到");
        }
        LogQueryRequestDto requestDto = new LogQueryRequestDto();
        requestDto.setSerialNo(SerialNoUtils.nextId());
        requestDto.setVersion(UriConstant.VERSION_NO);
        requestDto.setRequestTime(DateUtils.getCurrentDate());

        requestDto.setLogId(jobExecuteId);
        requestDto.setStartLine(startLine);
        requestDto.setEndLine(endLine);

        Map<String, String> header = null;
        if (StringUtils.hasLength(executeLog.getAuthToken())) {
            header = new HashMap<>(2);
            header.put(UriConstant.AUTHORIZATION_HEADER_KEY, executeLog.getAuthToken());
        }
        try {
            return this.remoteCaller.call(requestDto, header, this.remoteCaller.buildUri(executeLog.getEndpointIp(), executeLog.getEndpointPort(), UriConstant.LOG_QUERY), new TypeReference<ResultResponse<LogQueryResponseDto>>() {
            });
        } catch (RemoteCallException e) {
            log.error("查询任务执行日志错误", e);
            return ResultResponse.fail("EXECUTE-LOG-9998", e.getMessage());
        }
    }

    @ApiOperation("结束任务执行")
    @ApiImplicitParam(name = "executeLogId", value = "任务执行Id", required = true)
    @GetMapping("/cancel")
    public ResultResponse cancel(@RequestParam("executeLogId") String executeLogId) {
        JobExecuteLog executeLog = this.executeLogService.findById(executeLogId);
        if (executeLog == null) {
            return ResultResponse.fail("E-0001", "未找到执行记录");
        }
        if (!ExecuteResult.ExecuteResultCode.EXECUTING.getCode().equals(executeLog.getExecuteStatus())) {
            return ResultResponse.fail("E-0002", "执行记录不是执行中状态");
        }

        // 无论取消成功都置为任务取消
        executeLog.setExecuteStatus(ExecuteResult.ExecuteResultCode.MANUAL_CANCEL.getCode());
        this.executeLogService.updateById(executeLog);
        // 取消任务
        try {
            this.dynamicScheduleService.cancelExecute(executeLogId);
        } catch (RelayTaskIrrevocableException e) {
            return ResultResponse.fail("E-0003", e.getMessage());
        }
        return ResultResponse.ok("取消成功");
    }

    @ApiOperation("删除执行日志")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "jobExecuteId", value = "任务执行Id", required = true),
    })
    @GetMapping("/delete")
    public ResultResponse<LogDeleteResponseDto> delete(@RequestParam("jobExecuteId") String jobExecuteId) {
        JobExecuteLog executeLog = this.executeLogService.findById(jobExecuteId);
        if (executeLog == null) {
            return ResultResponse.fail("EXECUTE-LOG-9997", "执行记录未找到");
        }
        LogDeleteRequestDto requestDto = new LogDeleteRequestDto();
        requestDto.setSerialNo(SerialNoUtils.nextId());
        requestDto.setVersion(UriConstant.VERSION_NO);
        requestDto.setRequestTime(DateUtils.getCurrentDate());

        requestDto.setLogId(jobExecuteId);

        Map<String, String> header = null;
        if (StringUtils.hasLength(executeLog.getAuthToken())) {
            header = new HashMap<>(2);
            header.put(UriConstant.AUTHORIZATION_HEADER_KEY, executeLog.getAuthToken());
        }
        try {
            return this.remoteCaller.call(requestDto, header, this.remoteCaller.buildUri(executeLog.getEndpointIp(), executeLog.getEndpointPort(), UriConstant.LOG_DELETE), new TypeReference<ResultResponse<LogDeleteResponseDto>>() {
            });
        } catch (RemoteCallException e) {
            log.error("删除任务执行日志错误", e);
            return ResultResponse.fail("EXECUTE-LOG-9996", e.getMessage());
        }
    }

}
